[HVM] Sync per vcpu LAPIC timer with its TSC:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 20 Dec 2006 10:41:33 +0000 (10:41 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 20 Dec 2006 10:41:33 +0000 (10:41 +0000)
 - benefits LAPIC calibration
 - makes scheduling policy based on LAPIC more precise
 - makes LAPIC timer code becomes simpler and cleaner after using
   periodic time layer

Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/io.c
xen/arch/x86/hvm/irq.c
xen/arch/x86/hvm/svm/intr.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/hvm/vmx/intr.c
xen/arch/x86/hvm/vpt.c [new file with mode: 0644]
xen/include/asm-x86/hvm/vlapic.h
xen/include/asm-x86/hvm/vpt.h

index 945fff83e7d746f84f55931c5f1376cdebc08cdb..4939524128b294b043d4a06dee0b2a1f6baf5d13 100644 (file)
@@ -87,7 +87,8 @@ void hvm_migrate_timers(struct vcpu *v)
     pit_migrate_timers(v);
     rtc_migrate_timers(v);
     pmtimer_migrate_timers(v);
-    migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor);
+    if ( vcpu_vlapic(v)->pt.enabled )
+        migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor);
 }
 
 void hvm_do_resume(struct vcpu *v)
index b5221c962fcd070238f4d7ba15398854db5c38e0..013e723f35afb6c5f9191d7baa38f05aaf54647d 100644 (file)
@@ -689,21 +689,6 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
     }
 }
 
-void hvm_interrupt_post(struct vcpu *v, int vector, int type)
-{
-    pt_intr_post(v, vector, type);
-    
-    switch(type) {
-    case APIC_DM_EXTINT:
-        break;
-            
-    default:
-        vlapic_post_injection(v, vector, type);
-        break;
-    }
-}
-
-
 void hvm_io_assist(struct vcpu *v)
 {
     vcpu_iodata_t *vio;
index 238312e0f861750bdf8f98bcb96527b562ba5a70..ce2e11bcca9d8a2dcb9ee5487091a8a43bfedc86 100644 (file)
@@ -229,10 +229,9 @@ void hvm_set_callback_gsi(struct domain *d, unsigned int gsi)
 int cpu_has_pending_irq(struct vcpu *v)
 {
     struct hvm_domain *plat = &v->domain->arch.hvm_domain;
-    int dummy;
 
     /* APIC */
-    if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
+    if ( vlapic_has_interrupt(v) != -1 )
         return 1;
 
     /* PIC */
@@ -267,6 +266,9 @@ int get_intr_vector(struct vcpu* v, int irq, int type)
 
 int is_irq_masked(struct vcpu *v, int irq)
 {
+    if ( is_lvtt(v, irq) )
+        return !is_lvtt_enabled(v);
+
     if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7))
             && domain_vioapic(v->domain)->redirtbl[irq].fields.mask )
         return 1;
index 35ddbb55f48f3b4ed387e553b504b30c400ba67d..e3e0f0a40e69a768f5c03cf283869a0ae1263759 100644 (file)
@@ -141,7 +141,7 @@ asmlinkage void svm_intr_assist(void)
         break;
     }
 
-    hvm_interrupt_post(v, intr_vector, intr_type);
+    pt_intr_post(v, intr_vector, intr_type);
 }
 
 /*
index 86589658137ff070e127aad001b0467fe5076b7b..2280d946bb94718e908b26badccc5c0d3182a352 100644 (file)
@@ -39,9 +39,8 @@
 #define VLAPIC_VERSION                  0x00050014
 #define VLAPIC_LVT_NUM                  6
 
-extern u32 get_apic_bus_cycle(void);
-
-#define APIC_BUS_CYCLE_NS (((s_time_t)get_apic_bus_cycle()) / 1000)
+/* vlapic's frequence is 100 MHz */
+#define APIC_BUS_CYCLE_NS               10
 
 #define LVT_MASK \
     APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
@@ -122,11 +121,6 @@ static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
     return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
 }
 
-static void vlapic_set_irr(int vector, struct vlapic *vlapic)
-{
-    vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
-}
-
 static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
 {
     vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
@@ -433,46 +427,19 @@ static void vlapic_ipi(struct vlapic *vlapic)
 
 static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
 {
-    uint32_t counter_passed;
-    s_time_t passed, now = NOW();
-    uint32_t tmcct = vlapic_get_reg(vlapic, APIC_TMCCT);
-
-    if ( unlikely(now <= vlapic->timer_last_update) )
-    {
-        passed = ~0x0LL - vlapic->timer_last_update + now;
-        HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "time elapsed.");
-    }
-    else
-        passed = now - vlapic->timer_last_update;
+    struct vcpu *v = current;
+    uint32_t tmcct, tmict = vlapic_get_reg(vlapic, APIC_TMICT);
+    uint64_t counter_passed;
 
-    counter_passed = passed / (APIC_BUS_CYCLE_NS * vlapic->timer_divisor);
-
-    tmcct -= counter_passed;
-
-    if ( tmcct <= 0 )
-    {
-        if ( unlikely(!vlapic_lvtt_period(vlapic)) )
-        {
-            tmcct =  0;
-            /* FIXME: should we add interrupt here? */
-        }
-        else
-        {
-            do {
-                tmcct += vlapic_get_reg(vlapic, APIC_TMICT);
-            } while ( tmcct <= 0 );
-        }
-    }
-
-    vlapic->timer_last_update = now;
-    vlapic_set_reg(vlapic, APIC_TMCCT, tmcct);
+    counter_passed = (hvm_get_guest_time(v) - vlapic->pt.last_plt_gtime) // TSC
+                     * 1000000000ULL / ticks_per_sec(v) // NS
+                     / APIC_BUS_CYCLE_NS / vlapic->timer_divisor;
+    tmcct = tmict - counter_passed;
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
-      "timer initial count 0x%x, timer current count 0x%x, "
-      "update 0x%016"PRIx64", now 0x%016"PRIx64", offset 0x%x.",
-      vlapic_get_reg(vlapic, APIC_TMICT),
-      vlapic_get_reg(vlapic, APIC_TMCCT),
-      vlapic->timer_last_update, now, counter_passed);
+                "timer initial count %d, timer current count %d, "
+                "offset %"PRId64".",
+                tmict, tmcct, counter_passed);
 
     return tmcct;
 }
@@ -486,6 +453,9 @@ static void vlapic_set_tdcr(struct vlapic *vlapic, unsigned int val)
     /* Update the demangled timer_divisor. */
     val = ((val & 3) | ((val & 8) >> 1)) + 1;
     vlapic->timer_divisor = 1 << (val & 7);
+
+    HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+                "vlapic_set_tdcr timer_divisor: %d.", vlapic->timer_divisor);
 }
 
 static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
@@ -577,6 +547,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
      * According to the IA32 Manual, all accesses should be 32 bits.
      * Some OSes do 8- or 16-byte accesses, however.
      */
+    val &= 0xffffffff;
     if ( len != 4 )
     {
         unsigned int tmp;
@@ -671,6 +642,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
         break;
 
     case APIC_LVTT:         /* LVT Timer Reg */
+        vlapic->pt.irq = val & APIC_VECTOR_MASK;
     case APIC_LVTTHMR:      /* LVT Thermal Monitor */
     case APIC_LVTPC:        /* LVT Performance Counter */
     case APIC_LVT0:         /* LVT LINT0 Reg */
@@ -684,25 +656,16 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
 
     case APIC_TMICT:
     {
-        s_time_t now = NOW(), offset;
-
-        stop_timer(&vlapic->vlapic_timer);
+        uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->timer_divisor;
 
         vlapic_set_reg(vlapic, APIC_TMICT, val);
-        vlapic_set_reg(vlapic, APIC_TMCCT, val);
-        vlapic->timer_last_update = now;
-
-        offset = APIC_BUS_CYCLE_NS * vlapic->timer_divisor * val;
-
-        set_timer(&vlapic->vlapic_timer, now + offset);
+        create_periodic_time(&vlapic->pt, period, vlapic->pt.irq,
+                             vlapic_lvtt_period(vlapic), NULL, vlapic);
 
         HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                    "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
-                    "timer initial count 0x%x, offset 0x%016"PRIx64", "
-                    "expire @ 0x%016"PRIx64".",
-                    APIC_BUS_CYCLE_NS, now,
-                    vlapic_get_reg(vlapic, APIC_TMICT),
-                    offset, now + offset);
+                    "bus cycle is %uns, "
+                    "initial count %lu, period %"PRIu64"ns",
+                    APIC_BUS_CYCLE_NS, val, period);
     }
     break;
 
@@ -753,48 +716,6 @@ void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
                 "apic base msr is 0x%016"PRIx64".", vlapic->apic_base_msr);
 }
 
-void vlapic_timer_fn(void *data)
-{
-    struct vlapic *vlapic = data;
-    uint32_t timer_vector;
-    s_time_t now;
-
-    if ( unlikely(!vlapic_enabled(vlapic) ||
-                  !vlapic_lvt_enabled(vlapic, APIC_LVTT)) )
-        return;
-
-    timer_vector = vlapic_lvt_vector(vlapic, APIC_LVTT);
-    now = NOW();
-
-    vlapic->timer_last_update = now;
-
-    if ( vlapic_test_and_set_irr(timer_vector, vlapic) )
-        vlapic->timer_pending_count++;
-
-    if ( vlapic_lvtt_period(vlapic) )
-    {
-        s_time_t offset;
-        uint32_t tmict = vlapic_get_reg(vlapic, APIC_TMICT);
-
-        vlapic_set_reg(vlapic, APIC_TMCCT, tmict);
-
-        offset = APIC_BUS_CYCLE_NS * vlapic->timer_divisor * tmict;
-
-        set_timer(&vlapic->vlapic_timer, now + offset);
-    }
-    else
-        vlapic_set_reg(vlapic, APIC_TMCCT, 0);
-
-    vcpu_kick(vlapic_vcpu(vlapic));
-
-    HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
-                "now 0x%016"PRIx64", expire @ 0x%016"PRIx64", "
-                "timer initial count 0x%x, timer current count 0x%x.",
-                now, vlapic->vlapic_timer.expires,
-                vlapic_get_reg(vlapic, APIC_TMICT),
-                vlapic_get_reg(vlapic, APIC_TMCCT));
-}
-
 int vlapic_accept_pic_intr(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
@@ -809,7 +730,7 @@ int vlapic_accept_pic_intr(struct vcpu *v)
              vlapic_hw_disabled(vlapic)));
 }
 
-int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
+int vlapic_has_interrupt(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
     int highest_irr;
@@ -822,42 +743,22 @@ int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
          ((highest_irr & 0xF0) <= vlapic_get_ppr(vlapic)) )
         return -1;
 
-    *mode = APIC_DM_FIXED;
     return highest_irr;
 }
 
-void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
+int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
 {
+    int vector = vlapic_has_interrupt(v);
     struct vlapic *vlapic = vcpu_vlapic(v);
 
-    switch ( deliver_mode )
-    {
-    case APIC_DM_FIXED:
-    case APIC_DM_LOWEST:
-        vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
-        vlapic_clear_irr(vector, vlapic);
-        if ( (vector == vlapic_lvt_vector(vlapic, APIC_LVTT)) &&
-             (vlapic->timer_pending_count != 0) )
-        {
-            vlapic->timer_pending_count--;
-            vlapic_set_irr(vector, vlapic);
-        }
-        break;
-
-    case APIC_DM_REMRD:
-        gdprintk(XENLOG_WARNING, "Ignoring delivery mode 3.\n");
-        break;
-
-    case APIC_DM_SMI:
-    case APIC_DM_NMI:
-    case APIC_DM_INIT:
-    case APIC_DM_STARTUP:
-        break;
+    if ( vector == -1 )
+        return -1;
+    vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
+    vlapic_clear_irr(vector, vlapic);
 
-    default:
-        gdprintk(XENLOG_WARNING, "Invalid delivery mode\n");
-        break;
-    }
+    *mode = APIC_DM_FIXED;
+    return vector;
 }
 
 /* Reset the VLPAIC back to its power-on/reset state. */
@@ -918,8 +819,7 @@ int vlapic_init(struct vcpu *v)
     if ( v->vcpu_id == 0 )
         vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
 
-    init_timer(&vlapic->vlapic_timer,
-                  vlapic_timer_fn, vlapic, v->processor);
+    init_timer(&vlapic->pt.timer, pt_timer_fn, &vlapic->pt, v->processor);
 
     return 0;
 }
@@ -928,7 +828,22 @@ void vlapic_destroy(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
 
-    kill_timer(&vlapic->vlapic_timer);
+    kill_timer(&vlapic->pt.timer);
     unmap_domain_page_global(vlapic->regs);
     free_domheap_page(vlapic->regs_page);
 }
+
+int is_lvtt(struct vcpu *v, int vector)
+{
+    return vcpu_vlapic(v)->pt.enabled &&
+           vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT);
+}
+
+int is_lvtt_enabled(struct vcpu *v)
+{
+    if ( unlikely(!vlapic_enabled(vcpu_vlapic(v))) ||
+            !vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT)) 
+        return 0;
+
+    return 1;
+}
index 5b104bc43bb71d3806d5bdf6a88c3264fd6e603f..5be7aaeb0250108cc6cd80225a25080bc6aeee01 100644 (file)
@@ -175,8 +175,8 @@ asmlinkage void vmx_intr_assist(void)
         BUG();
         break;
     }
-    
-    hvm_interrupt_post(v, highest_vector, intr_type);
+
+    pt_intr_post(v, highest_vector, intr_type);
 }
 
 /*
diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c
new file mode 100644 (file)
index 0000000..cb320bb
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * vpt.c: Virtual Platform Timer
+ *
+ * Copyright (c) 2006, Xiaowei Yang, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <xen/time.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vpt.h>
+#include <asm/event.h>
+
+static __inline__ void missed_ticks(struct periodic_time *pt)
+{
+    s_time_t missed_ticks;
+
+    missed_ticks = NOW() - pt->scheduled;
+    if ( missed_ticks > 0 ) 
+    {
+        missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
+        if ( missed_ticks > 1000 )
+        {
+            /* TODO: Adjust guest time together */
+            pt->pending_intr_nr++;
+        }
+        else
+        {
+            pt->pending_intr_nr += missed_ticks;
+        }
+        pt->scheduled += missed_ticks * pt->period;
+    }
+}
+
+void pt_freeze_time(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+
+    if ( test_bit(_VCPUF_blocked, &v->vcpu_flags) )
+        return;
+
+    v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
+
+    list_for_each( list, head )
+    {
+        pt = list_entry(list, struct periodic_time, list);
+        stop_timer(&pt->timer);
+    }
+}
+
+void pt_thaw_time(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+
+    if ( v->arch.hvm_vcpu.guest_time )
+    {
+        hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
+        v->arch.hvm_vcpu.guest_time = 0;
+
+        list_for_each( list, head )
+        {
+            pt = list_entry(list, struct periodic_time, list);
+            missed_ticks(pt);
+            set_timer(&pt->timer, pt->scheduled);
+        }
+    }
+}
+
+/* Hook function for the platform periodic time */
+void pt_timer_fn(void *data)
+{
+    struct periodic_time *pt = data;
+
+    pt->pending_intr_nr++;
+    pt->scheduled += pt->period;
+
+    missed_ticks(pt);
+
+    if ( !pt->one_shot )
+        set_timer(&pt->timer, pt->scheduled);
+
+    vcpu_kick(pt->vcpu);
+}
+
+void pt_update_irq(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+    uint64_t max_lag = -1ULL;
+    int irq = -1;
+
+    list_for_each( list, head )
+    {
+        pt = list_entry(list, struct periodic_time, list);
+        if ( !is_irq_masked(v, pt->irq) && pt->pending_intr_nr 
+                && pt->last_plt_gtime + pt->period < max_lag )
+        {
+            max_lag = pt->last_plt_gtime + pt->period;
+            irq = pt->irq;
+        }
+    }
+
+    if ( is_lvtt(v, irq) )
+        vlapic_set_irq(vcpu_vlapic(v), irq, 0);
+    else if ( irq >= 0 )
+    {
+        hvm_isa_irq_deassert(v->domain, irq);
+        hvm_isa_irq_assert(v->domain, irq);
+    }
+}
+
+struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+    struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+    int vec;
+
+    list_for_each( list, head )
+    {
+        pt = list_entry(list, struct periodic_time, list);
+        if ( !pt->pending_intr_nr )
+            continue;
+
+        if ( is_lvtt(v, pt->irq) )
+        {
+            if (pt->irq == vector)
+                return pt;
+            else
+                continue;
+        }
+
+        vec = get_intr_vector(v, pt->irq, type);
+
+        /* RTC irq need special care */
+        if ( vector != vec || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
+            continue;
+
+        return pt;
+    }
+
+    return NULL;
+}
+
+void pt_intr_post(struct vcpu *v, int vector, int type)
+{
+    struct periodic_time *pt = is_pt_irq(v, vector, type);
+
+    if (pt == NULL)
+        return;
+
+    pt->pending_intr_nr--;
+    pt->last_plt_gtime += pt->period_cycles;
+    hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
+
+    if (pt->cb)
+        pt->cb(pt->vcpu, pt->priv);
+}
+
+/* If pt is enabled, discard pending intr */
+void pt_reset(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+
+    list_for_each( list, head )
+    {
+       pt = list_entry(list, struct periodic_time, list);
+       if ( pt->enabled )
+        {
+            pt->pending_intr_nr = 0;
+            pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
+            pt->scheduled = NOW() + pt->period;
+            set_timer(&pt->timer, pt->scheduled);
+        }
+    }
+}
+
+void create_periodic_time(struct periodic_time *pt, uint64_t period,
+                          uint8_t irq, char one_shot, time_cb *cb, void *data)
+{
+    destroy_periodic_time(pt);
+
+    pt->enabled = 1;
+    if (period < 900000) /* < 0.9 ms */
+    {
+        printk("HVM_PlatformTime: program too small period %"PRIu64"\n", period);
+        period = 900000; /* force to 0.9ms */
+    }
+    pt->period = period;
+    pt->vcpu = current;
+    pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
+    pt->irq = irq;
+    pt->period_cycles = (u64)period * cpu_khz / 1000000L;
+    pt->one_shot = one_shot;
+    pt->scheduled = NOW() + period;
+    pt->cb = cb;
+    pt->priv = data;
+
+    list_add(&pt->list, &current->arch.hvm_vcpu.tm_list);
+    set_timer(&pt->timer, pt->scheduled);
+}
+
+void destroy_periodic_time(struct periodic_time *pt)
+{
+    if ( pt->enabled )
+    {
+        pt->enabled = 0;
+        pt->pending_intr_nr = 0;
+        list_del(&pt->list);
+        stop_timer(&pt->timer);
+    }
+}
index 3691e3ca4f99d1cdba50271a37d31e34af6ac9cf..0137b34515693ee56d8a53dfe3920fd971f680b2 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/msr.h>
 #include <public/hvm/ioreq.h>
+#include <asm/hvm/vpt.h>
 
 #define MAX_VECTOR      256
 
 #define vlapic_enabled(vlapic)      (!vlapic_disabled(vlapic))
 
 struct vlapic {
-    uint64_t           apic_base_msr;
-    uint32_t           disabled; /* VLAPIC_xx_DISABLED */
-    uint32_t           timer_divisor;
-    struct timer       vlapic_timer;
-    int                timer_pending_count;
-    s_time_t           timer_last_update;
-    struct page_info   *regs_page;
-    void               *regs;
+    uint64_t             apic_base_msr;
+    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
+    uint32_t             timer_divisor;
+    struct periodic_time pt;
+    int                  timer_pending_count;
+    s_time_t             timer_last_update;
+    struct page_info     *regs_page;
+    void                 *regs;
 };
 
 static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
@@ -70,13 +71,11 @@ static inline void vlapic_set_reg(
     *((uint32_t *)(vlapic->regs + reg)) = val;
 }
 
-
 int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
 
-void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode);
-
 int vlapic_find_highest_irr(struct vlapic *vlapic);
 
+int vlapic_has_interrupt(struct vcpu *v);
 int cpu_get_apic_interrupt(struct vcpu *v, int *mode);
 
 int  vlapic_init(struct vcpu *v);
@@ -91,4 +90,7 @@ struct vlapic *apic_round_robin(
 
 int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
 
+int is_lvtt(struct vcpu *v, int vector);
+int is_lvtt_enabled(struct vcpu *v);
+
 #endif /* __ASM_X86_HVM_VLAPIC_H__ */
index b43007ea5e1c76474543ed2bbb9f5ab9e5abe518..dd45d37fa7fb4652382ad454a69b1826cd9a221c 100644 (file)
@@ -42,10 +42,10 @@ struct periodic_time {
     struct list_head list;
     char enabled;
     char one_shot;              /* one shot time */
-    int irq;
+    u8 irq;
     struct vcpu *vcpu;          /* vcpu timer interrupt delivers to */
     u32 pending_intr_nr;        /* the couner for pending timer interrupts */
-    u32 period;                 /* frequency in ns */
+    u64 period;                 /* frequency in ns */
     u64 period_cycles;          /* frequency in cpu cycles */
     s_time_t scheduled;         /* scheduled timer interrupt */
     u64 last_plt_gtime;         /* platform time when last IRQ is injected */
@@ -115,8 +115,8 @@ void pt_update_irq(struct vcpu *v);
 struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
 void pt_intr_post(struct vcpu *v, int vector, int type);
 void pt_reset(struct vcpu *v);
-void create_periodic_time(struct periodic_time *pt, u32 period, char irq, 
-                          char one_shot, time_cb *cb, void *data);
+void create_periodic_time(struct periodic_time *pt, uint64_t period,
+                          uint8_t irq, char one_shot, time_cb *cb, void *data);
 void destroy_periodic_time(struct periodic_time *pt);
 
 int pv_pit_handler(int port, int data, int write);